package com.springboot.file.constant;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;

/**
 * 通用返回结果类
 * <p>
 * 用于统一系统的返回格式，包含状态码、消息、数据等信息。
 * </p>
 *
 * @param <T> 返回数据的类型
 * @author liuc
 * @since 1.0
 */
@Data
@Schema(description = "通用返回结果")
public class Result<T> implements Serializable {

    /**
     * 返回码
     */
    @Schema(description = "返回码")
    private String code;

    /**
     * 返回消息
     */
    @Schema(description = "返回消息")
    private String msg;

    /**
     * 是否成功
     */
    @Schema(description = "是否成功")
    private boolean success;

    /**
     * 设置是否成功
     * @param success 是否成功
     */
    public void setSuccess(boolean success) {
        this.success = success;
    }

    /**
     * 全局唯一ID
     */
    @Schema(description = "全局唯一ID")
    private String traceId;

    /**
     * 返回数据，可能为 {@code null}
     */
    @Schema(description = "返回数据")
    private transient T data;

    /**
     * 时间戳
     */
    @Schema(description = "时间戳")
    private long timestamp;

    /**
     * 默认构造函数
     */
    public Result() {
    }

    /**
     * 使用结果代码构造结果对象
     *
     * @param resultCode 结果代码
     */
    Result(ResultCode resultCode) {
        this.code = resultCode.getCode();
        this.msg = resultCode.getMessage();
        this.timestamp = System.currentTimeMillis();
    }

    /**
     * 使用自定义代码和消息构造结果对象
     *
     * @param code 自定义代码
     * @param message 自定义消息
     */
    private Result(String code, String message) {
        this.code = code;
        this.msg = message;
        this.timestamp = System.currentTimeMillis();
    }

    /**
     * 设置结果代码和消息
     *
     * @param resultCode 结果代码
     */
    private void setResultCode(ResultCode resultCode) {
        this.code = resultCode.getCode();
        this.msg = resultCode.getMessage();
    }

    /**
     * 返回成功结果，不包含数据
     *
     * @param <T> 数据类型
     * @return 成功结果对象
     */
    public static <T> Result<T> success() {
        return new Result<>(ResultCode.SUCCESS);
    }

    /**
     * 返回包含数据的成功结果
     *
     * @param data 返回数据，可为 {@code null}
     * @param <T> 数据类型
     * @return 包含数据的成功结果对象
     */
    public static <T> Result<T> success(T data) {
        Result<T> result = new Result<>(ResultCode.SUCCESS);
        result.data = data;
        return result;
    }

    /**
     * 返回包含数据和自定义消息的成功结果
     *
     * @param data 返回数据，可为 {@code null}
     * @param message 自定义消息
     * @param <T> 数据类型
     * @return 包含数据和自定义消息的成功结果对象
     */
    public static <T> Result<T> success(T data, String message) {
        Result<T> result = new Result<>(ResultCode.SUCCESS.getCode(), message);
        result.data = data;
        return result;
    }

    /**
     * 返回包含分页结果的成功结果
     *
     * @param pageResult 分页结果
     * @param <T> 数据类型
     * @return 包含分页结果的成功结果对象
     */
    public static <T> Result<T> success(IPageResult<T> pageResult) {
        return new IPageResult<>(pageResult);
    }

    /**
     * 返回包含自定义分页数据的成功结果
     *
     * @param pageNo 页码
     * @param pageSize 每页大小
     * @param totalPage 总页数
     * @param totalRows 总行数
     * @param data 返回数据，可为 {@code null}
     * @param <T> 数据类型
     * @return 包含自定义分页数据的成功结果对象
     */
    public static <T> Result<T> success(int pageNo, int pageSize, long totalPage, long totalRows, T data) {
        return new IPageResult<>(pageNo, pageSize, totalPage, totalRows, data);
    }

    /**
     * 返回系统错误结果
     *
     * @param <T> 数据类型
     * @return 系统错误结果对象
     */
    public static <T> Result<T> error() {
        return new Result<>(ResultCode.SYSTEM_ERROR);
    }

    /**
     * 返回自定义错误代码的错误结果
     *
     * @param resultCode 结果代码
     * @param <T> 数据类型
     * @return 自定义错误代码的错误结果对象
     */
    public static <T> Result<T> error(ResultCode resultCode) {
        Result<T> result = new Result<>();
        result.setSuccess(false);
        result.setResultCode(resultCode);
        return result;
    }

    /**
     * 返回包含自定义消息的系统错误结果
     *
     * @param message 自定义消息
     * @param <T> 数据类型
     * @return 包含自定义消息的系统错误结果对象
     */
    public static <T> Result<T> error(String message) {
        return new Result<>(ResultCode.SYSTEM_ERROR.getCode(), message);
    }

    /**
     * 返回包含自定义代码和消息的错误结果
     *
     * @param code 自定义代码
     * @param message 自定义消息
     * @param <T> 数据类型
     * @return 包含自定义代码和消息的错误结果对象
     */
    public static <T> Result<T> error(String code, String message) {
        return new Result<>(code, message);
    }

    /**
     * 返回自定义结果代码的结果
     *
     * @param code 结果代码
     * @param <T> 数据类型
     * @return 自定义结果代码的结果对象
     */
    public static <T> Result<T> result(ResultCode code) {
        return new Result<>(code.getCode(), code.getMessage());
    }

    /**
     * 返回包含数据和自定义结果代码的结果
     *
     * @param data 返回数据，可为 {@code null}
     * @param code 结果代码
     * @param <T> 数据类型
     * @return 包含数据和自定义结果代码的结果对象
     */
    public static <T> Result<T> result(T data, ResultCode code) {
        Result<T> result = new Result<>(code.getCode(), code.getMessage());
        result.data = data;
        return result;
    }

    /**
     * 返回包含数据和自定义代码、消息的结果
     *
     * @param data 返回数据，可为 {@code null}
     * @param code 自定义代码
     * @param message 自定义消息
     * @param <T> 数据类型
     * @return 包含数据和自定义代码、消息的结果对象
     */
    public static <T> Result<T> result(T data, String code, String message) {
        Result<T> result = new Result<>(code, message);
        result.data = data;
        return result;
    }

    /**
     * 判断是否成功
     *
     * @return 如果结果代码为成功代码则返回 {@code true}，否则返回 {@code false}
     */
    public boolean isSuccess() {
        return ResultCode.SUCCESS.getCode().equals(this.code);
    }

    /**
     * 设置全局唯一ID
     *
     * @param traceId 全局唯一ID
     * @return 当前对象
     */
    public Result<T> setTraceId(String traceId) {
        this.traceId = traceId;
        return this;
    }
}

